package com.ujiuye.filter;

import com.ujiuye.pojo.Employee;
import com.ujiuye.pojo.RoleEmployee;
import com.ujiuye.pojo.User;
import com.ujiuye.service.EmployeeService;
import com.ujiuye.service.UserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.List;

public class ShiroDbRealm extends AuthorizingRealm {
    @Autowired
    private EmployeeService employeeService;

    public static final String SESSION_USER_KEY = "LOGIN_SESSION";

    /**
     * 授权查询回调函数,进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定
     * 用户的访问控制的方法
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        Employee user = (Employee) SecurityUtils.getSubject().getSession().getAttribute(ShiroDbRealm.SESSION_USER_KEY);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        List<RoleEmployee> roles = user.getRoles();
        for (RoleEmployee role : roles) {
            info.addRole(role.getRole().getRolename().trim());//加入当前用户权限
        }
        return info;
    }

    //认证回调函数,登录信息和用户验证信息
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authToken) throws AuthenticationException {
        //把token转换成User对象
        Employee employee = tokenToEmployee((UsernamePasswordToken) authToken);
        //验证用户是否可以登录
        Employee ui = employeeService.login(employee.getUsername(),employee.getPassword());
        if (ui == null){
            return null;
        }
        //设置session
        Session session = SecurityUtils.getSubject().getSession();
        session.setAttribute(ShiroDbRealm.SESSION_USER_KEY,ui);
        //当前Realm的name
        String realmName = this.getName();
        //登录的主要信息: 可以是一个实体类的对象,但该实体类的对象一定是根据token的username查询到的
        Object principal = authToken.getPrincipal();
        return new SimpleAuthenticationInfo(principal,employee.getPassword(),realmName);
    }

    //把token转换成User对象
    private Employee tokenToEmployee(UsernamePasswordToken authToken){
        Employee employee = new Employee();
        employee.setUsername(authToken.getUsername());
        employee.setPassword(String.valueOf(authToken.getPassword()));
        return employee;
    }
}
